package com.hm.shopping.service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;

import com.hm.common.def.DataStatusDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageInfoParam;
import com.hm.common.util.ChineseToPinYinUtil;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.DateUtil;
import com.hm.common.util.Optional;
import com.hm.shopping.auto.su.BaseDomain;
import com.hm.shopping.domain.ClassificationDetailDomain;
import com.hm.shopping.domain.ClassificationDomain;
import com.hm.shopping.domain.QClassificationDetailDomain;
import com.hm.shopping.domain.QClassificationDomain;
import com.hm.shopping.repository.ClassificationDetailRepository;
import com.hm.shopping.repository.ClassificationRepository;
import com.hm.shopping.su.BeanUtil;
import com.hm.shopping.vo.ClassificationDetailVo;
import com.hm.shopping.vo.ClassificationVo;
import com.querydsl.core.types.dsl.BooleanExpression;

/**
 * @author shishun.wang
 * @date 2018年1月18日 下午6:26:57
 * @version 1.0
 * @describe
 */
@Service
public class ClassificationServiceImpl implements ClassificationService {

	@Autowired
	private ClassificationRepository classificationRepository;

	@Autowired
	private ClassificationDetailRepository classificationDetailRepository;

	@Override
	public void addClassification(ClassificationVo classificationVo) {
		if (CommonUtil.isAnyEmpty(classificationVo.getClassificationName(), classificationVo.getClassificationOrder(), classificationVo.getClassificationIcon())) {
			throw ServiceException.warning(ErrorCode.PARAMETERS_MISSING);
		}

		classificationVo.setClassificationCode(ChineseToPinYinUtil.getPingYin(classificationVo.getClassificationName().replace("/", "_or_")).toUpperCase());
		ClassificationDomain domain = new ClassificationDomain();
		BeanUtil.copyProperties(classificationVo, domain);
		BaseDomain.initBaseInfo(domain);
		classificationRepository.save(domain);
	}

	@Override
	public void addClassificationDetail(ClassificationDetailVo classificationDetailVo) {
		if (CommonUtil.isAnyEmpty(classificationDetailVo.getClassificationId(), classificationDetailVo.getClassificationDetailIcon(), classificationDetailVo.getClassificationDetailName(), classificationDetailVo.getAttributes())) {
			throw ServiceException.warning(ErrorCode.PARAMETERS_MISSING);
		}

		ClassificationDomain classificationDomain = classificationRepository.findOne(classificationDetailVo.getClassificationId());
		if (CommonUtil.isEmpty(classificationDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND, "商品分类");
		}

		ClassificationDetailDomain domain = new ClassificationDetailDomain();
		BeanUtil.copyProperties(classificationDetailVo, domain);
		BaseDomain.initBaseInfo(domain);
		domain.setClassificationDetailCode(ChineseToPinYinUtil.getPingYin(classificationDetailVo.getClassificationDetailName().replace("/", "_or_")).toUpperCase());

		classificationDetailVo.setAttributes(classificationDetailVo.getAttributes().parallelStream().map(attr -> {

			attr.setAttributeCode(ChineseToPinYinUtil.getPingYin(attr.getAttributeType().replace("/", "_or_")).toUpperCase());
			attr.setAttributes(attr.getAttributes().parallelStream().map(attrDetail -> {
				attrDetail.setCode(ChineseToPinYinUtil.getPingYin(attrDetail.getName().replace("/", "_or_")).toUpperCase());
				return attrDetail;
			}).collect(Collectors.toList()));

			return attr;
		}).collect(Collectors.toList()));

		classificationDetailRepository.save(domain);

		List<String> classificationDetailIds = classificationDomain.getClassificationDetailIds();
		classificationDetailIds.add(domain.getId());
		classificationRepository.save(classificationDomain);
	}

	@Override
	public List<ClassificationVo> getWebClassifications() {
		Pageable pageable = new QPageRequest(0, 10, QClassificationDomain.classificationDomain.classificationOrder.desc());

		return Optional.of(classificationRepository.findAll(QClassificationDomain.classificationDomain.status.eq(DataStatusDef.ENABLE), pageable).getContent()).map(items -> {
			return items.parallelStream().map(item -> {
				ClassificationVo vo = new ClassificationVo();
				BeanUtil.copyProperties(item, vo);
				vo.setCreateTime(DateUtil.data2long(item.getCreateTime()));

				vo.setClassificationDetails(Optional.of(item.getClassificationDetailIds()).map(detailIds -> {
					QClassificationDetailDomain qClassificationDetailDomain = QClassificationDetailDomain.classificationDetailDomain;
					return classificationDetailRepository.findAll(qClassificationDetailDomain.id.in(detailIds).and(qClassificationDetailDomain.status.eq(DataStatusDef.ENABLE)));
				}).map(detailItems -> {

					List<ClassificationDetailVo> detailVos = new ArrayList<ClassificationDetailVo>();
					detailItems.forEach(detailItem -> {
						ClassificationDetailVo detailVo = new ClassificationDetailVo();
						BeanUtil.copyProperties(detailItem, detailVo);
						detailVo.setCreateTime(DateUtil.data2long(item.getCreateTime()));

						detailVos.add(detailVo);
					});

					return detailVos;
				}).get());

				return vo;
			}).collect(Collectors.toList());
		}).get();
	}

	@Override
	public PageInfo<ClassificationVo> queryClassifications(PageInfoParam pageParam, String classificationName) {
		QClassificationDomain qClassificationDomain = QClassificationDomain.classificationDomain;

		Pageable pageable = new QPageRequest(pageParam.getPage(), pageParam.getSize(), qClassificationDomain.createTime.desc());
		BooleanExpression predicate = qClassificationDomain.status.eq(DataStatusDef.ENABLE);
		if (CommonUtil.isNotEmpty(classificationName)) {
			predicate = predicate.and(qClassificationDomain.classificationName.like(classificationName));
		}

		Page<ClassificationDomain> page = classificationRepository.findAll(predicate, pageable);
		List<ClassificationVo> vos = page.getContent().parallelStream().map(item -> {
			ClassificationVo vo = new ClassificationVo();
			BeanUtil.copyProperties(item, vo);
			vo.setCreateTime(item.getCreateTime().getTime());
			return vo;
		}).collect(Collectors.toList());

		return new PageInfo<ClassificationVo>(vos, page.getTotalPages(), page.getTotalElements());
	}

	@Override
	public List<ClassificationDetailVo> getClassificationDetailList(String classificationId) {
		if (CommonUtil.isEmpty(classificationId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}
		ClassificationDomain classificationDomain = classificationRepository.findOne(classificationId);
		if (CommonUtil.isEmpty(classificationDomain)) {
			return new ArrayList<ClassificationDetailVo>(0);
		}

		QClassificationDetailDomain qClassificationDetailDomain = QClassificationDetailDomain.classificationDetailDomain;
		List<ClassificationDetailVo> vos = new ArrayList<ClassificationDetailVo>();
		classificationDetailRepository.findAll(qClassificationDetailDomain.id.in(classificationDomain.getClassificationDetailIds()).and(qClassificationDetailDomain.status.eq(DataStatusDef.ENABLE))).iterator().forEachRemaining(item -> {
			ClassificationDetailVo vo = new ClassificationDetailVo();
			BeanUtil.copyProperties(item, vo);
			vo.setCreateTime(item.getCreateTime().getTime());
			vos.add(vo);
		});

		return vos;
	}

	@Override
	public void updateClassification(ClassificationVo classificationVo) {
		if (CommonUtil.isAnyEmpty(classificationVo.getId(), classificationVo.getClassificationName(), classificationVo.getClassificationOrder(), classificationVo.getClassificationIcon())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ClassificationDomain classificationDomain = classificationRepository.findOne(classificationVo.getId());
		if (CommonUtil.isEmpty(classificationDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		classificationDomain.setClassificationName(classificationVo.getClassificationName());
		classificationVo.setClassificationCode(ChineseToPinYinUtil.getPingYin(classificationVo.getClassificationName().replace("/", "_or_")).toUpperCase());
		classificationDomain.setClassificationIcon(classificationVo.getClassificationIcon());
		classificationDomain.setClassificationOrder(classificationVo.getClassificationOrder());

		classificationRepository.save(classificationDomain);
	}

	@Override
	public void updateClassificationDetail(ClassificationDetailVo classificationDetailVo) {
		if (CommonUtil.isAnyEmpty(classificationDetailVo.getId(), classificationDetailVo.getClassificationDetailName(), classificationDetailVo.getAttributes(), classificationDetailVo.getClassificationDetailOrder(), classificationDetailVo.getClassificationDetailIcon())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ClassificationDetailDomain classificationDetailDomain = classificationDetailRepository.findOne(classificationDetailVo.getId());
		if (CommonUtil.isEmpty(classificationDetailDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		classificationDetailDomain.setClassificationDetailName(classificationDetailVo.getClassificationDetailName());
		classificationDetailDomain.setClassificationDetailCode(ChineseToPinYinUtil.getPingYin(classificationDetailVo.getClassificationDetailName().replace("/", "_or_")).toUpperCase());
		classificationDetailDomain.setClassificationDetailIcon(classificationDetailVo.getClassificationDetailIcon());
		classificationDetailDomain.setClassificationDetailOrder(classificationDetailVo.getClassificationDetailOrder());

		classificationDetailDomain.setAttributes(classificationDetailVo.getAttributes().parallelStream().map(attr -> {

			attr.setAttributeCode(ChineseToPinYinUtil.getPingYin(attr.getAttributeType().replace("/", "_or_")).toUpperCase());
			attr.setAttributes(attr.getAttributes().parallelStream().map(attrDetail -> {
				attrDetail.setCode(ChineseToPinYinUtil.getPingYin(attrDetail.getName().replace("/", "_or_")).toUpperCase());
				return attrDetail;
			}).collect(Collectors.toList()));

			return attr;
		}).collect(Collectors.toList()));

		classificationDetailRepository.save(classificationDetailDomain);
	}

	@Override
	public void deleteClassification(String classificationId) {
		if (CommonUtil.isEmpty(classificationId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ClassificationDomain classificationDomain = classificationRepository.findOne(classificationId);
		if (CommonUtil.isEmpty(classificationDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}
		classificationDomain.setStatus(DataStatusDef.DISABLE);
		classificationRepository.save(classificationDomain);
	}

	@Override
	public void deleteClassificationDetail(String classificationDetailId) {
		if (CommonUtil.isEmpty(classificationDetailId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ClassificationDetailDomain classificationDetailDomain = classificationDetailRepository.findOne(classificationDetailId);
		if (CommonUtil.isEmpty(classificationDetailDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		classificationDetailDomain.setStatus(DataStatusDef.DISABLE);
		classificationDetailRepository.save(classificationDetailDomain);
	}

	@Override
	public ClassificationVo getClassification(String classificationId) {
		if (CommonUtil.isEmpty(classificationId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ClassificationDomain classificationDomain = classificationRepository.findOne(classificationId);
		if (CommonUtil.isEmpty(classificationDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		ClassificationVo vo = new ClassificationVo();
		BeanUtil.copyProperties(classificationDomain, vo);
		return vo;
	}

	@Override
	public ClassificationDetailVo getClassificationDetail(String classificationDetailId) {
		if (CommonUtil.isEmpty(classificationDetailId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ClassificationDetailDomain classificationDetailDomain = classificationDetailRepository.findOne(classificationDetailId);
		if (CommonUtil.isEmpty(classificationDetailDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		ClassificationDetailVo vo = new ClassificationDetailVo();
		BeanUtil.copyProperties(classificationDetailDomain, vo);
		return vo;
	}

	@Override
	public ClassificationDetailVo getClassificationDetailByCode(String classificationDetailCode) {
		if (CommonUtil.isEmpty(classificationDetailCode)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ClassificationDetailDomain classificationDetailDomain = classificationDetailRepository.findOne(QClassificationDetailDomain.classificationDetailDomain.classificationDetailCode.eq(classificationDetailCode));
		if (CommonUtil.isNotEmpty(classificationDetailDomain)) {
			ClassificationDetailVo vo = new ClassificationDetailVo();
			BeanUtil.copyProperties(classificationDetailDomain, vo);
			return vo;
		}

		return null;
	}

	@Override
	public List<ClassificationDetailVo> getClassificationDetailsByCcode(String classificationCode) {
		List<ClassificationDetailVo> vos = new ArrayList<ClassificationDetailVo>();
		if (CommonUtil.isEmpty(classificationCode)) {
			return vos;
		}
		ClassificationDomain classificationDomain = classificationRepository.findOne(QClassificationDomain.classificationDomain.classificationCode.eq(classificationCode));
		if (CommonUtil.isEmpty(classificationDomain)) {
			return vos;
		}
		classificationDetailRepository.findAll(QClassificationDetailDomain.classificationDetailDomain.id.in(classificationDomain.getClassificationDetailIds())).forEach(item -> {
			ClassificationDetailVo vo = new ClassificationDetailVo();
			BeanUtil.copyProperties(item, vo);

			vos.add(vo);
		});
		return vos;
	}

}
